package com.neteast.bustruck.ui

import android.Manifest
import android.annotation.SuppressLint
import android.content.res.Configuration
import android.location.LocationManager
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.webkit.ConsoleMessage
import android.webkit.JsResult
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.widget.LinearLayout
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.google.android.gms.location.LocationRequest
import com.just.agentweb.AgentWeb
import com.just.agentweb.AgentWebUIControllerImplBase
import com.just.agentweb.WebChromeClient
import com.just.agentweb.WebViewClient
import com.neteast.bustruck.R
import com.neteast.bustruck.common.Common
import com.neteast.bustruck.db.AppDataBase
import com.neteast.bustruck.db.entiys.LocalSaveInfo
import com.neteast.bustruck.db.entiys.TmActionRequest
import com.neteast.bustruck.db.entiys.TmLogUpdateRequest
import com.neteast.bustruck.db.entiys.TmTruckLoadForm
import com.neteast.bustruck.db.entiys.TmTruckRequest
import com.neteast.bustruck.db.entiys.TruckInfo
import com.neteast.bustruck.db.entiys.TruckLogInfo
import com.neteast.bustruck.db.entiys.User
import com.neteast.bustruck.http.ApiService
import com.neteast.bustruck.http.RetrofitClient
import com.neteast.bustruck.http.entiys.OrderUploadInfo
import com.neteast.bustruck.jsbridge.Callback
import com.neteast.bustruck.jsbridge.IBridgeHandler
import com.neteast.bustruck.jsbridge.JsBridgeHandler
import com.neteast.bustruck.netbus.NetStatusBus
import com.neteast.bustruck.netbus.annotation.NetSubscribe
import com.neteast.bustruck.netbus.type.Mode
import com.neteast.bustruck.netbus.type.NetType
import com.neteast.bustruck.utils.GsonUtils
import com.neteast.bustruck.utils.NetworkUtils
import com.neteast.bustruck.utils.SPUtils
import com.neteast.bustruck.utils.Utils
import com.neteast.bustruck.utils.location.LocationHelper
import com.permissionx.guolindev.PermissionX
import com.scwang.smart.refresh.header.ClassicsHeader
import com.scwang.smart.refresh.layout.listener.OnRefreshListener
import com.scwang.smart.refresh.layout.listener.ScrollBoundaryDecider
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeoutOrNull


class MainActivity : AppCompatActivity() ,CoroutineScope by MainScope() , IBridgeHandler by JsBridgeHandler() {


    val TAG = "test_log"
    private val  localDataBase by lazy {
        AppDataBase.getInstance(this)
    }

    private var isLocationPermission = false

     lateinit var  mRequest: LocationRequest



    private lateinit var apiService:ApiService
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()

        setContentView(R.layout.activity_main)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }
//        ImmersionBar.with(this)
//            .transparentStatusBar()
//            .transparentNavigationBar()
//            .init()
        NetStatusBus.getInstance().register(this)


        mLocationManager = getSystemService(LocationManager::class.java)
        apiService = RetrofitClient.instance.create(ApiService::class.java)


        initWebConfig()


        PermissionX.init(this)
            .permissions(Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION)
            .request { allGranted, grantedList, deniedList ->
                if(allGranted){
                    isLocationPermission = true
                }
            }
        initUserToken()
    }

    private fun initUserToken() {
        launch {
            try {
                var lastUserName  = getLastUserName()
                if(lastUserName.isNotEmpty()){
                    localDataBase.userDao().findByName(lastUserName).let {
                        RetrofitClient.token = it?.token?:""
                    }
                }
            }catch (e:Exception){
            }
        }
    }


    private lateinit var mAgentWeb: AgentWeb
    private lateinit var webLayout:WebLayout
    private  var mWebChromeClient =object : WebChromeClient(){
        override fun onJsAlert(p0: WebView?, p1: String?, p2: String?, p3: JsResult?): Boolean {
            return super.onJsAlert(p0, p1, p2, p3)
        }

        override fun onConsoleMessage(p0: ConsoleMessage?): Boolean {
            Utils.logshow("onConsoleMessage: ${p0?.message()}")
            return super.onConsoleMessage(p0)
        }
    }

    /**
     * 初始化浏览器相关操作
     */
    @SuppressLint("MissingPermission")
    private fun initWebConfig() {

        webLayout = WebLayout(this)
//        webLayout.layout.setRefreshHeader(ClassicsHeader(this))
//        webLayout.layout.setOnRefreshListener(OnRefreshListener { refreshlayout ->
//            mAgentWeb.webCreator.webView.reload()
//            webLayout.layout.finishRefresh(500)
//        })
        webLayout.layout.setEnableRefresh(false)

        mAgentWeb = AgentWeb.with(this)
            .setAgentWebParent(
                findViewById(R.id.layout_container),
                LinearLayout.LayoutParams(-1, -1)
            )
            .useDefaultIndicator()
            .interceptUnkownUrl()
            .setAgentWebUIController(AgentWebUIControllerImplBase())
            .setWebChromeClient(mWebChromeClient)
            .setWebViewClient(object :WebViewClient(){
                override fun onPageFinished(p0: WebView?, p1: String?) {
                    super.onPageFinished(p0, p1)
                    webLayout.layout.finishRefresh()
                }

                override fun onReceivedError(
                    p0: WebView?,
                    p1: WebResourceRequest?,
                    p2: WebResourceError?
                ) {
                    super.onReceivedError(p0, p1, p2)
                    webLayout.layout.finishRefresh()
                }

            })
            .setSecurityType(AgentWeb.SecurityType.STRICT_CHECK)
            .setWebLayout(webLayout)
            .createAgentWeb()
            .ready().get()

        try {
            val usergent = mAgentWeb.agentWebSettings.webSettings.userAgentString
            mAgentWeb.agentWebSettings.webSettings.userAgentString = "$usergent  Android"
        } catch (e: Exception) {
            e.printStackTrace()
        }
        mAgentWeb.agentWebSettings.webSettings.javaScriptEnabled=true
        mAgentWeb.agentWebSettings.webSettings.loadWithOverviewMode=true
        mAgentWeb.agentWebSettings.webSettings.domStorageEnabled=true
        mAgentWeb.agentWebSettings.webSettings.databaseEnabled=true

        attach(mAgentWeb.webCreator.webView)

        mAgentWeb.urlLoader.loadUrl(Common.LOCAL_ROOT)




        //回调通知网络当前网络状态
        registerBridger(Common.HANDLER_GET_NETSTATE_NAME){ _, callback ->
            var mode =  NetworkUtils.getNetType()
            var isNet = NetworkUtils.isNetworkAvailable()
            var result = mapOf("isNetConnect" to isNet,"netMode" to mode)
            var str =   GsonUtils.toJson(result)
            Utils.logshow( "获取网络状态: $str")
            callback?.invoke(result)
        }




        //获取gps信息
        registerBridger(Common.HANDLER_GET_GPSINFO_NAME){ _, callback ->
            if(checkGpsOpen()){
                if(isLocationPermission){
                    Log.d(TAG,"获取gps信息")

                    val exceptionHandler = CoroutineExceptionHandler { _, exception ->
                        var result = mapOf("success" to false,"data" to "获取失败")
                        callback?.invoke(result)
                    }
                    launch(exceptionHandler) {
                        val location = LocationHelper.getLocation(this@MainActivity)
                        val map = HashMap<String, String>()
                        map["latitude"] = "${location.latitude}"
                        map["longitude"] = "${location.longitude}"
                        var result = mapOf("success" to true,"data" to map)
                        callback?.invoke(result)
                    }


                }else{
                    var result = mapOf("success" to false,"data" to "缺少权限")
                    callback?.invoke(result)
                }

            }else{
                var result = mapOf("success" to false,"data" to "设备gps没有打开")
                callback?.invoke(result)
            }
        }



        //写入用户信息
        registerBridger(Common.HANDLER_WRITE_USERINFO_NAME){data,callBack->
            Utils.logshow( "用户信息: $data")
          GsonUtils.fromJson<User>(data,User::class.java)?.let {
              launch {
                  RetrofitClient.token = it.token?:""
                  val oldUserInfo = localDataBase.userDao().findByName(it.username)
                  try {
                      if(oldUserInfo!=null){
                          it.uid = oldUserInfo.uid
                          localDataBase.userDao().updateUser(it)
                      }else{
                          localDataBase.userDao().insertUser(it)
                      }
                      saveLastUserInfo(it.username)
                      callBack?.invoke(mapOf("success" to true))
                  }catch (e:Exception){
                      e.printStackTrace()
                  }
              }
          }


        }


        //加载本地用户信息
        registerBridger(Common.HANDLER_GET_USERINFO_NAME){_,callBack->
            Utils.logshow( "获取本地用户信息")
            launch {
                try {
                    var lastUserName  = getLastUserName()
                    if(lastUserName.isNotEmpty()){
                        localDataBase.userDao().findByName(lastUserName)?.let {
                            RetrofitClient.token = it.token?:""
                            callBack?.invoke(it.username)
                        }
                    }else{
                        callBack?.invoke(null)
                    }
                }catch (e:Exception){
                    callBack?.invoke(null)
                }
            }
        }




        //写入订单详情
        registerBridger(Common.HANDLER_WRITE_TRUCKLOAD_NAME){data,callBack->
            Utils.logshow( " writBusTruck truck信息: $data")
            GsonUtils.fromJson<TmTruckLoadForm>(data,TmTruckLoadForm::class.java)?.let { item->
                launch {
                    item.truck_id?.let {localId->
                        val oldUserInfo = localDataBase.truckLoadDao().getTruckLoad(localId)
                        try {
                            if(oldUserInfo!=null){
                                item.uid = oldUserInfo.uid
                                item.update_time=System.currentTimeMillis()
                                var count =   localDataBase.truckLoadDao().updateLocalInfo(item)
                               Utils.logshow( "truck信息 更新 $count")
                            }else{
                                var count =      localDataBase.truckLoadDao().insertList(item)
                                Utils.logshow( "truck信息 插入$count")
                            }
                            callBack?.invoke(mapOf("success" to true))
                        }catch (e:Exception){
                            Utils.logshow( "truck信息  ${e.message}")
                            callBack?.invoke(mapOf("success" to false))
                        }
                    }
                }
            }
        }

        //获取订单详情
        registerBridger(Common.HANDLER_READ_TRUCKLOAD_NAME){data,callBack->
            Utils.logshow( "truck 请求参数：$data")
            launch {
                GsonUtils.fromJson<TmTruckRequest>(data,TmTruckRequest::class.java)?.let {
                    try {
                        Utils.logshow( "truck 获取参数：${GsonUtils.toJson(it)}")
                        if(it.currentTruckLoadId?.isNullOrEmpty()==true){
                            callBack?.invoke(null)
                        }else{
                            var result = localDataBase.truckLoadDao().getTruckLoad(it.currentTruckLoadId!!)
                            if(result!=null){
                                Utils.logshow( "truck 返回js结果：${result.data}")
                               val info = GsonUtils.fromJson<TruckInfo>(result.data,TruckInfo::class.java)
                                if(info!=null){
                                    info.truck_id = it.currentTruckLoadId
                                }
                               withContext(Dispatchers.Main){
                                   callBack?.invoke(info)
                               }
                            }else{
                                withContext(Dispatchers.Main) {
                                    callBack?.invoke(null)
                                }
                            }
                        }
                    }catch (e:Exception){
                        withContext(Dispatchers.Main) {
                            callBack?.invoke(null)
                        }
                    }
                }
            }
        }



        //写入日志
        registerBridger(Common.HANDLER_WRITE_TRUCKLOG_NAME){data,callBack->
            Utils.logshow( "log信息: $data")
            GsonUtils.fromJson<TruckLogInfo>(data,TruckLogInfo::class.java)?.let {
                launch {
                    Utils.logshow( "log信息转化后: ${GsonUtils.toJson(it)}")
                    try {
                        localDataBase.truckLogDao().insertList(it)
                        callBack?.invoke(mapOf("success" to true))
                    }catch (e:Exception){
                        e.printStackTrace()
                        callBack?.invoke(mapOf("success" to false))
                    }
                }
            }
        }


        //后台开始上报日志
        registerBridger(Common.HANDLER_START_UPLOAD_NAME){data,callBack->
            Utils.logshow( "后台开始上报日志:$data")
            GsonUtils.fromJson<TmLogUpdateRequest>(data, TmLogUpdateRequest::class.java)?.let {
                startUpdateActionById(it,callBack)
            }
        }



        //写入配置
        registerBridger(Common.HANDLER_WRITE_CONFIG_NAME){data,callBack->
            Utils.logshow( "配置信息: $data")
            GsonUtils.fromJson<LocalSaveInfo>(data, LocalSaveInfo::class.java)?.let { item->
                launch {

                        val oldInfo = localDataBase.infoDao().getLocalBaseInfo(item.action)
                        try {
                            if(oldInfo!=null){
                                oldInfo.data = item.data
                                localDataBase.infoDao().updateLocalInfo(oldInfo)
                            }else{
                                localDataBase.infoDao().insertList(item)
                            }
                            callBack?.invoke(mapOf("success" to true))
                        }catch (e:Exception){
                            Utils.logshow( "truck信息  ${e.message}")
                            callBack?.invoke(mapOf("success" to false))
                        }
                }
            }
        }

        //获取配置
        registerBridger(Common.HANDLER_READ_CONFIG_NAME){data,callBack->
            Utils.logshow( "配置 请求参数：$data")
            launch {
                GsonUtils.fromJson<TmActionRequest>(data,TmActionRequest::class.java)?.let {
                    try {
                        Utils.logshow( "配置 获取参数：${GsonUtils.toJson(it)}")
                        if(it.action?.isNullOrEmpty()==true){
                            callBack?.invoke(null)
                        }else{
                            var result = localDataBase.infoDao().getLocalBaseInfo(it.action)
                            if(result!=null){
                                Utils.logshow( "truck 返回js结果：${result.data}")
                                withContext(Dispatchers.Main){
                                    callBack?.invoke(result)
                                }
                            }else{
                                withContext(Dispatchers.Main) {
                                    callBack?.invoke(null)
                                }
                            }
                        }
                    }catch (e:Exception){
                        withContext(Dispatchers.Main) {
                            callBack?.invoke(null)
                        }
                    }
                }
            }
        }

        
    }


    private var isUploading = false
    private fun startUpdateActionList() {
        Utils.logshow("开始后台上传   isUpload:$isUploading")
        if(isUploading){
            return
        }
        val userName = getLastUserName()
        Utils.logshow("开始后台上传   username:$userName")
        if(!TextUtils.isEmpty(userName)){
            isUploading=true
            launch {
                try {
                    withContext(Dispatchers.IO){
                        localDataBase.truckLoadDao().getTruckLoadForUpdate(userName)?.let { list->
                            for (item in list){
                                Utils.logshow("上报订单详情  原始数据: ${GsonUtils.toJson(item)}")
                                if(item.is_update){
                                    if(NetworkUtils.isNetworkAvailable()){
                                        localDataBase.truckLogDao().getTruckLoadListByTruckId(item.truck_id!!,false)?.let {
                                            for (d in it){
                                                Utils.logshow("startUpdateActionLis  原始数据: ${GsonUtils.toJson(d)}")
                                                d.getUploadInfm()?.let { info ->
                                                    Utils.logshow("startUpdateActionList: ${GsonUtils.toJson(info)}")
                                                    if(NetworkUtils.isNetworkAvailable()){
                                                        withTimeoutOrNull(Common.NET_TIMEOUT_TIME){
                                                            apiService.uploadAddAction(info)
                                                        }?.let { reposen->
                                                            if(reposen.success){
                                                                d.is_update=true
                                                                localDataBase.truckLogDao().updateLocalInfo(d)
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }else{
                                    if(NetworkUtils.isNetworkAvailable()){
                                        withTimeoutOrNull(Common.NET_TIMEOUT_TIME){
                                            apiService.creaetOrUpdateOrderInfo(OrderUploadInfo(item.truck_id,userName,GsonUtils.toJson(item)))
                                        }?.let { reposen->
                                            if(reposen.success){
                                                item.is_update=true
                                                localDataBase.truckLoadDao().updateLocalInfo(item)
                                                delay(8000)
                                                localDataBase.truckLogDao().getTruckLoadListByTruckId(item.truck_id!!,false)?.let {
                                                    for (d in it){
                                                        Utils.logshow("startUpdateActionLis  原始数据: ${GsonUtils.toJson(d)}")
                                                        d.getUploadInfm()?.let { info ->
                                                            Utils.logshow("startUpdateActionList: ${GsonUtils.toJson(info)}")
                                                            if(NetworkUtils.isNetworkAvailable()){
                                                                withTimeoutOrNull(Common.NET_TIMEOUT_TIME){
                                                                    apiService.uploadAddAction(info)
                                                                }?.let { reposen->
                                                                    if(reposen.success){
                                                                        d.is_update=true
                                                                        localDataBase.truckLogDao().updateLocalInfo(d)
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    isUploading=false
                }catch (e:Exception){
                    e.printStackTrace()
                    isUploading=false
                }

            }
        }
    }


    private fun startUpdateActionById(data: TmLogUpdateRequest, callBack: Callback?) {
        Utils.logshow( "startUpdateActionById 请求参数：${data.currentCircleId}")
        if(isUploading){
            return
        }

        if(data.currentCircleId.isNotEmpty()){
            isUploading=true
            launch {
                try {
                    withContext(Dispatchers.IO){
                        var list = localDataBase.truckLogDao().getTruckLoadListByOrderId(data.currentCircleId!!,false)
                        if(list!=null){
                            for (item in list){
                                Utils.logshow(
                                    "startUpdateActionLis  原始数据: ${
                                        GsonUtils.toJson(
                                            item
                                        )
                                    }"
                                )
                                item.getUploadInfm()?.let { info ->
                                    Utils.logshow("startUpdateActionList: ${GsonUtils.toJson(info)}")
                                    withTimeoutOrNull(Common.NET_TIMEOUT_TIME){
                                        apiService.uploadAddAction(info)
                                    }?.let { reposen->
                                        if(reposen.success){
                                            item.is_update=true
                                            localDataBase.truckLogDao().updateLocalInfo(item)
                                        }
                                    }
                                }
                            }
                            isUploading=false
                            callBack?.invoke(mapOf("success" to true))
                        }else{
                            isUploading=false
                            callBack?.invoke(mapOf("success" to true))
                        }
                    }
                }catch (e:Exception){
                    isUploading=false
                    callBack?.invoke(mapOf("success" to false))
                }
            }
        }
    }


    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)
    }

    override fun onDestroy() {
        super.onDestroy()
        NetStatusBus.getInstance().unregister(this)
        cancel()
        detach()
    }

   private lateinit var mLocationManager:LocationManager

    private fun checkGpsOpen():Boolean{

        return mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
    }



    /**
     * 当网络变化的时候工作
     */
    @NetSubscribe(mode = Mode.AUTO)
    fun workNoneNet(netType: NetType) {
        Utils.logshow("当前网络状态：${netType.name}")
        if(netType!=NetType.NONE){
            startUpdateActionList()
        }
    }



    /**
     * 保存上一个用户信息
     */
    private fun saveLastUserInfo( name:String=""){
        SPUtils.getInstance().put(Common.SP_LAST_USERNAME,name)
    }

    /**
     * 获取上一次用户姓名
     */
    private fun getLastUserName():String{
        return SPUtils.getInstance().getString(Common.SP_LAST_USERNAME)
    }




}